JS - array - map method
for eachlus, maar dan specifiek voor het omzetten van waarden. Eén invoerwaarde komt overeen met één 'getransformeerd' output waarde.
Syntaxis
array.map(function(currentValue,index,arr), thisValue)
Parameters
Parameter | Beschrijving | ||||||||
---|---|---|---|---|---|---|---|---|---|
function(currentValue, index, arr) | verplicht, een functie die voor elk element in de array uitgevoerd zal worden Functie argumenten:
|
||||||||
thisValue | optioneel: een waarde die aan de functie meegegeven kan worden en die als haar "this" waarde kan optreden |
Toepassing
Een klassieke, procedurele manier om dat te bewerkstelligen is:
var numberList = [6, 7, 8, 9]; var newNumberList = []; for(var i = 0; i < numberList.length; i++) { newNumberList[i] = numberList[i] * 2; } console.log("The list of doubled numbers: ", newNumberList); // [2, 4, 6, 8]
Deze code doet wat er verwacht van wordt maar het kan beter, efficënter. Het is een omslachtige manier om een vrij eenvoudige taak uit te voeren, namelijk het verdubbelen van alle getallen in een array.
Wat als we gewoon de intentie de getallen in de array te verdubbelen konden schrijven en dan aangeven dat op de elementen in de array toe te passen?
var numberList = [3, 2, 6, 5]; var newNumberList = numberList.map(function(number){ return number * 2; }); console.log("The doubled numbers are", newNumberList); // [6, 4, 12, 10]
We hebben geen lus meer nodig, en we hoeven niet handmatig de getallen toe te voegen aan een array. We definiëren onze intentie, en laat map
het werk doen.
Dit kan ook gemakkelijk worden geketend:
var numberList = [1, 2, 3, 4]; var newNumberList = numberList.map(function(number){ return number * 2; }).map(function(number){ return number + 1; }); console.log("The list of doubled and incremented numbers: ", newNumberList); // [3, 5, 7, 9]
We kunnen onze intentie ook in een benoemde functie definiëren en verschillende keren na elkaar oproepen. Om bijvoorbeeld een getal te verviervoudigen kunnen we twee keer de methoude double twee keer aan elkaar ketenen:
var numberList = [1, 2, 3, 4]; var double = function(a) { return a * 2; } var newNumberList = numberList.map(double).map(double); console.log("The list of doubled and incremented numbers: ", newNumberList); // [4,8,12,16]
Elk getal wordt nu twee keer verdubbeld. We moeten de arrays niet handmatig beheren. We gebruiken gewoon functies die een transformatie toepassen op een enkele waarde.
Je moet wel rekening houden met enkele 'regels' voor de map
functies. JavaScript verplicht het niet om die regels na te leven. De regels toch naleven maakt het een stuk makkelijker om te begrijpen wat de code doet.
- Het aantal invoerelementen is gelijk aan het aantal uitvoerelementen
Je kan in demap
methode geent 4 waarden invoeren, en er slechts 3 terugkrijgen. Als de bron-array X aantal elementen heeft, zal de resulterende aray ook X aantal elementen bevatten. Elk uitvoerelement komt overeen met het invoerelement in dezelfde positie. Ze worden nooit rond geschud. - De callback functies mogen geen ingevoerde waarden
muteren
Dit betekent dat je moet geen objecten of arrays rechtstreeks vanuit je callback functies mag wijzigen. Je kan best de invoerwaarde van een object of een array klonen het in plaats daarvan, en de kopie ervan wijzigen.
Op deze manier is er een garantie dat je callback geen neveneffecten veroorzaakt. Dat wil zeggen dat, wat er ook gebeurt in je callback, het alleeninvloed heeft op de kopie. Dit zorgt voor betrouwbare code.
Je kan een array in Javascript met dearray.slice (0)
methode klonen. Dat is echterondiep klonen
, namelijk als de waarden in de array zelf arrays of objecten zijn, hebben die nog steeds dezelfde waarden als in de originele array.
Diepe-klonen
maken van een object is ingewikkelder. In een CommonJS omgeving (Node.js, Webpack, Browserify, ...), kan je gebruik maken van deXtend
module. In het slechtste geval maak je zelf een functie:functie clone (o) { var newO = {}; for (var keyin o) { newO [key] = o[key]; } return newO; } var cloned = clone(originalObject);
Er is een uitzondering op deze regel, maar we dat later krijgt - gewoon aannemen dat deze regel altijd van toepassing, tenzij anders aangegeven. - Geen neveneffecten veroorzaken
Doe nooit iets in eenmap
methode dat de 'state' ergens anders wijzigt. - Maar vertragen die callbacks en al dat klonen niet het programma?
Daarover hoef je je geen zorgen te maken. Deze operaties lopen als een trein in Javascript, vooral in de V8-gebaseerde engines zoals Node.js. Code schrijf je in de eerste plaats voor de leesbaarheid. Prestatie komt op de tweede plaats. Het is veel gemakkelijker om leesbare code te optimaliseren, dan geoptimaliseerde code leesbaar te maken.
Maar wat als ik wil alleen een deel van de waarden te transformeren?
Misschien is uw bron array heeft een aantal waarden die u wilt transformeren, en een aantal waarden die u wil gewoon helemaal weg te gooien. Dat is niet mogelijk met kaart alleen, het aantal invoerwaarden en het aantal uitvoerwaarden voor een kaart gesprek altijd gelijk.
En met map
kan je meer dan eenvoudige transformaties uitvoeren. Je methode kan gebruik maken van twee extra parameters, de lopende index
en de array
zelf. In het volgende voorbeeld:
var starter = [1, 2, 3]; function multiplyByNextElement (value, i, a) { var next = i + 1; // If at the end of array // use the first element if (next === a.length) { next = 0; } return value * a[next]; } var newA = starter.map(multiplyByNextElement); console.log(newA); // Outputs: [2, 6, 3]
wordt het volgende element gebruikt om de transformatie uit te voeren.
Bronnen
- Una Kravets, An Illustrated (and Musical) Guide to Map, Reduce, and Filter Array Methods, Mar 26, 2019
- M. David Green, Using Map and Reduce in Functional JavaScript, March 28, 2016